\chapter{dji\+\_\+motor }
\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor}{}\label{md_modules_2motor_2_d_j_imotor_2dji__motor}\index{dji\_motor@{dji\_motor}}
\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md66}%
\Hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md66}%




\href{mailto:neozng1@hnu.edu.cn}{\texttt{neozng1@hnu.\+edu.\+cn}}

\begin{quote}
TODO\+:


\begin{DoxyEnumerate}
\item 给不同的电机设置不同的低通滤波器惯性系数而不是统一使用宏
\item 为\+M2006和\+M3508增加开环的零位校准函数 
\end{DoxyEnumerate}\end{quote}


\DoxyHorRuler{0}


\begin{quote}
建议将电机的反馈频率通过\+Robo\+Master Assistant统一设置为500\+Hz。当前默认的{\ttfamily Motor\+Task()}执行频率为500\+Hz，若不修改电机反馈频率可能导致单条总线挂载的电机数量有限，且容易出现帧错误和仲裁失败的情况。 \end{quote}
\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md68}{}\doxysection{\texorpdfstring{总览和封装说明}{总览和封装说明}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md68}
\begin{quote}
如果你不需要理解该模块的工作原理，你只需要查看这一小节。 \end{quote}


dji\+\_\+motor模块对\+DJI智能电机，包括\+M2006，\+M3508以及\+GM6020进行了详尽的封装。你不再需要关心\+PID的计算以及\+CAN报文的发送和接收解析，你只需要专注于根据应用层的需求，设定合理的期望值，并通过{\ttfamily DJIMotor\+Set\+Ref()}设置对应电机的输入参考即可。

\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}==设定值的单位==\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}


\begin{DoxyEnumerate}
\item ==位置环为\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}角度制\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}（0-\/360，total\+\_\+angle可以为任意值）==
\item ==速度环为角速度，单位为\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}度/每秒\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}（deg/sec）==
\item ==电流环为A==
\item ==GM6020的输入设定为\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}力矩\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，待测量（-\/30000\texorpdfstring{$\sim$}{\string~}30000）==

==M3508的输入设定为-\/20\+A\texorpdfstring{$\sim$}{\string~}20A （-\/16384\texorpdfstring{$\sim$}{\string~}16384）==

==M2006的输入设定为-\/10\+A\texorpdfstring{$\sim$}{\string~}10A （-\/10000\texorpdfstring{$\sim$}{\string~}10000）==
\end{DoxyEnumerate}

如果你希望更改电机的反馈来源，比如进入小陀螺模式/视觉模式（这时候你想要云台保持静止，使用\+IMU的yaw角度值作为反馈来源），只需要调用{\ttfamily DJIMotor\+Change\+Feed()}，电机便可立刻切换反馈数据来源至\+IMU。

要获得一个电机，请通过{\ttfamily DJIMotor\+Init()}并传入一些参数，他就会返回一个电机的指针。你也不再需要查看这些电机和电调的说明书，\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}只需要设置其电机id\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}（6020为拨码开关值，2006和3508为电调的闪动次数），该模块会自动为你计算\+CAN发送和接收\+ID并搞定所有硬件层的琐事。

初始化电机时，你需要传入的参数包括：


\begin{DoxyItemize}
\item \texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}电机挂载的\+CAN总线设置\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，\+CAN1 or CAN2，以及电机的id，使用{\ttfamily can\+\_\+instance\+\_\+config\+\_\+s}封装，只需要设置这两个参数\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{CAN\_HandleTypeDef\ *can\_handle;}
\DoxyCodeLine{uint32\_t\ tx\_id;\ \textcolor{comment}{//\ tx\_id设置为电机id,不需要查说明书计算，直接为电调的闪动次数或拨码开关值，为1-\/8}}

\end{DoxyCode}

\item \texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}电机类型\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，使用{\ttfamily Motor\+\_\+\+Type\+\_\+e}：


\begin{DoxyCode}{0}
\DoxyCodeLine{GM6020\ =\ 0}
\DoxyCodeLine{M3508\ \ =\ 1}
\DoxyCodeLine{M2006\ \ =\ 2}

\end{DoxyCode}

\item {\bfseries{电机控制设置}}
\begin{DoxyItemize}
\item 闭环类型


\begin{DoxyCode}{0}
\DoxyCodeLine{OPEN\_LOOP}
\DoxyCodeLine{CURRENT\_LOOP\ }
\DoxyCodeLine{SPEED\_LOOP\ }
\DoxyCodeLine{ANGLE\_LOOP\ }
\DoxyCodeLine{CURRENT\_LOOP\ |\ SPEED\_LOOP\ \ \ \ \ \ \ \textcolor{comment}{//\ 同时对电流和速度闭环}}
\DoxyCodeLine{SPEED\_LOOP\ \ \ |\ ANGLE\_LOOP\ \ \ \ \ \ \ \textcolor{comment}{//\ 同时对速度和位置闭环}}
\DoxyCodeLine{CURRENT\_LOOP\ |\ SPEED\_LOOP\ |ANGLE\_LOOP\ \textcolor{comment}{//\ 三环全开}}

\end{DoxyCode}

\item 是否反转

{\ttfamily c MOTOR\+\_\+\+DIRECTION\+\_\+\+NORMAL MOTOR\+\_\+\+DIRECTION\+\_\+\+REVERSE }
\item 是否其他反馈来源，以及他们对应的数据指针（如果有的话）

\`{}\`{}\`{}c MOTOR\+\_\+\+FEED = 0 
\end{DoxyItemize}
\end{DoxyItemize}\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md69}{}\doxysection{\texorpdfstring{OTHER\+\_\+\+FEED = 1}{OTHER\+\_\+\+FEED = 1}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md69}
// 电流只能从电机传感器获得所以无法设置其他来源 \`{}\`{}\`{}


\begin{DoxyItemize}
\item 每个环的\+PID参数以及是否使用改进功能，以及其他反馈来源指针（如果在上一步启用了其他数据来源）

\`{}\`{}\`{}c typedef struct // config parameter \{ float Kp; float Ki; float Kd;

float Max\+Out; // 输出限幅 // 以下是优化参数 float Integral\+Limit; // 积分限幅 float Dead\+Band; // 死区 float CoefA; // For Changing Integral float CoefB; // ITerm = Err\texorpdfstring{$\ast$}{*}((A-\/abs(err)+B)/A) when B\texorpdfstring{$<$}{<}\texorpdfstring{$\vert$}{|}err\texorpdfstring{$\vert$}{|}\texorpdfstring{$<$}{<}A+B float Output\+\_\+\+LPF\+\_\+\+RC; // RC = 1/omegac float Derivative\+\_\+\+LPF\+\_\+\+RC;

PID\+\_\+\+Improvement\+\_\+e Improve; // 优化环节，定义在下一个代码块 \} PIDInit\+\_\+config\+\_\+s; // 只有当你设启用了对应的优化环节，优化参数才会生效 \`{}\`{}\`{}

{\ttfamily c typedef enum \{ NONE = 0b00000000, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Integral\+\_\+\+Limit = 0b00000001, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Derivative\+\_\+\+On\+\_\+\+Measurement = 0b00000010, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Trapezoid\+\_\+\+Intergral = 0b00000100, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Proportional\+\_\+\+On\+\_\+\+Measurement = 0b00001000, Output\+Filter = 0b00010000, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Changing\+Integration\+Rate = 0b00100000, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Derivative\+Filter = 0b01000000, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} Error\+Handle = 0b10000000, \textbackslash{}ilinebr\texorpdfstring{$<$}{<}br\texorpdfstring{$>$}{>} \} PID\+\_\+\+Improvement\+\_\+e; // 若希望使用多个环节的优化，这样就行：\+Integral\+\_\+\+Limit \texorpdfstring{$\vert$}{|}\+Trapezoid\+\_\+\+Intergral\texorpdfstring{$\vert$}{|}...\texorpdfstring{$\vert$}{|}... }

{\ttfamily c float \texorpdfstring{$\ast$}{*}other\+\_\+angle\+\_\+feedback\+\_\+ptr float \texorpdfstring{$\ast$}{*}other\+\_\+speed\+\_\+feedback\+\_\+ptr }
\end{DoxyItemize}

\DoxyHorRuler{0}


推荐的初始化参数编写格式如下：


\begin{DoxyCode}{0}
\DoxyCodeLine{\mbox{\hyperlink{struct_motor___init___config__s}{Motor\_Init\_Config\_s}}\ config\ =\ \{}
\DoxyCodeLine{\ \ .motor\_type\ =\ M3508,\ \ \textcolor{comment}{//\ 要注册的电机为3508电机}}
\DoxyCodeLine{\ \ .can\_init\_config\ =\ \{.can\_handle\ =\ \&hcan1,\ \textcolor{comment}{//\ 挂载在CAN1}}
\DoxyCodeLine{\ \ \ \ \ \ \ .tx\_id\ =\ 1\},\ \ \ \ \ \ \ \ \ \ \textcolor{comment}{//\ C620每隔一段时间闪动1次,设置为1}}
\DoxyCodeLine{\ \ \textcolor{comment}{//\ 采用电机编码器角度与速度反馈,启用速度环和电流环,不反转,最外层闭环为速度环}}
\DoxyCodeLine{\ \ \ \ \ \ \ \ .controller\_setting\_init\_config\ =\ \{.angle\_feedback\_source\ =\ MOTOR\_FEED,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .outer\_loop\_type\ =\ SPEED\_LOOP,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .close\_loop\_type\ =\ SPEED\_LOOP\ |\ CURRENT\_LOOP,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ .speed\_feedback\_source\ =\ MOTOR\_FEED,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ .motor\_reverse\_flag\ =\ MOTOR\_DIRECTION\_NORMAL\},}
\DoxyCodeLine{\ \ \ \ \ \textcolor{comment}{//\ 电流环和速度环PID参数的设置,不采用计算优化则不需要传入Improve参数}}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \textcolor{comment}{//\ 不使用其他数据来源(如IMU),不需要传入反馈数据变量指针}}
\DoxyCodeLine{\ \ .controller\_param\_init\_config\ =\ \{.current\_PID\ =\ \{.Improve\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kp\ =\ 1,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Ki\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kd\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .DeadBand\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .MaxOut\ =\ 4000\},}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ .speed\_PID\ =\ \{.Improve\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kp\ =\ 1,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Ki\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kd\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .DeadBand\ =\ 0,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .MaxOut\ =\ 4000\}\}\};}
\DoxyCodeLine{}
\DoxyCodeLine{dji\_motor\_instance\ *djimotor\ =\ \mbox{\hyperlink{dji__motor_8h_ae6a2dbd0d46fc7d80c6e2339aad09969}{DJIMotorInit}}(config);\ \textcolor{comment}{//\ 设置好参数后进行初始化并保留返回的指针}}

\end{DoxyCode}


\DoxyHorRuler{0}


要控制一个\+DJI电机，我们提供了2个接口：


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_afc682af85b4e84a7a74d01097cf738e5}{DJIMotorSetRef}}(dji\_motor\_instance\ *motor,\ \textcolor{keywordtype}{float}\ ref);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_af949d3574538d826035110bf7e05c2f8}{DJIMotorChangeFeed}}(dji\_motor\_instance\ *motor,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \mbox{\hyperlink{motor__def_8h_a306d656c63a2d986e7aff57a0526395d}{Closeloop\_Type\_e}}\ loop,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Feedback\_Source\_e\ type);}

\end{DoxyCode}


调用第一个并传入设定值，它会自动根据你设定的\+PID参数进行动作。 如果对不同闭环都有参考输入,则设置最外层的闭环(通过此函数)并将剩下的参考输入通过前馈数据指针进行设定

调用第二个并设定要修改的反馈环节和反馈类型，它会将反馈数据指针切换到你设定好的变量（需要在初始化的时候设置反馈指针）。

\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}如果需要获取电机的反馈数据\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}（如小陀螺模式需要根据麦克纳姆轮逆运动学解算底盘速度），直接通过你拥有的{\ttfamily dji\+\_\+motor\+\_\+instance}访问成员变量：


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{comment}{//\ LeftForwardMotor是一个dji\_motor\_instance实例}}
\DoxyCodeLine{\textcolor{keywordtype}{float}\ speed=LeftForwardMotor-\/>motor\_measure-\/>speed\_rpm;}
\DoxyCodeLine{...}

\end{DoxyCode}


{\itshape {\bfseries{现在，忘记\+PID的计算和发送、接收以及协议解析，专注于模块之间的逻辑交互吧。}}}

\DoxyHorRuler{0}
\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md73}{}\doxysection{\texorpdfstring{代码结构}{代码结构}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md73}
.h文件内包括了外部接口和类型定义,以及模块对应的宏。c文件内为私有函数和外部接口的定义。

motor\+\_\+def.\+h内包含了一些电机通用的定义。\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md74}{}\doxysection{\texorpdfstring{类型定义}{类型定义}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md74}

\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ DJI\_MOTOR\_CNT\ 12}}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ SPEED\_SMOOTH\_COEF\ 0.9f\ \ \ \ }\textcolor{comment}{//\ better\ to\ be\ greater\ than\ 0.85}}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ CURRENT\_SMOOTH\_COEF\ 0.98f\ }\textcolor{comment}{//\ this\ coef\ must\ be\ greater\ than\ 0.95}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{struct\ }\textcolor{comment}{/*\ DJI电机CAN反馈信息*/}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ uint16\_t\ ecd;}
\DoxyCodeLine{\ \ \ \ uint16\_t\ last\_ecd;}
\DoxyCodeLine{\ \ \ \ int16\_t\ speed\_rpm;}
\DoxyCodeLine{\ \ \ \ int16\_t\ given\_current;}
\DoxyCodeLine{\ \ \ \ uint8\_t\ temperate;}
\DoxyCodeLine{\ \ \ \ int16\_t\ total\_round;}
\DoxyCodeLine{\ \ \ \ int32\_t\ total\_angle;}
\DoxyCodeLine{\}\ dji\_motor\_measure;}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{struct}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ \textcolor{comment}{/*\ motor\ measurement\ recv\ from\ CAN\ feedback\ */}}
\DoxyCodeLine{\ \ \ \ dji\_motor\_measure\ motor\_measure;}
\DoxyCodeLine{\ \ \ \ \textcolor{comment}{/*\ basic\ config\ of\ a\ motor*/}}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{struct_motor___control___setting__s}{Motor\_Control\_Setting\_s}}\ motor\_settings;}
\DoxyCodeLine{\ \ \ \ \textcolor{comment}{/*\ controller\ used\ in\ the\ motor\ (3\ loops)*/}}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{struct_motor___controller__s}{Motor\_Controller\_s}}\ motor\_controller;}
\DoxyCodeLine{\ \ \ \ \textcolor{comment}{/*\ the\ CAN\ instance\ own\ by\ motor\ instance*/}}
\DoxyCodeLine{\ \ \ \ can\_instance\ motor\_can\_instance;}
\DoxyCodeLine{\ \ \ \ \textcolor{comment}{/*\ sender\ assigment*/}}
\DoxyCodeLine{\ \ \ \ uint8\_t\ sender\_group;}
\DoxyCodeLine{\ \ \ \ uint8\_t\ message\_num;}
\DoxyCodeLine{\ }
\DoxyCodeLine{\ \ \ uint8\_t\ stop\_flag;}
\DoxyCodeLine{\ \ \ \ }
\DoxyCodeLine{\ \ \ \ Motor\_Type\_e\ motor\_type;}
\DoxyCodeLine{\}\ dji\_motor\_instance;}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily DJI\+\_\+\+MOTOR\+\_\+\+CNT}是允许的最大\+DJI电机数量，根据经验，暂定为每个\+CAN6个，防止出现拥塞。
\item {\ttfamily SPEED\+\_\+\+SMOOTH\+\_\+\+COEF}和{\ttfamily CURRENT\+\_\+\+SMOOTH\+\_\+\+COEF}是电机反馈的电流和速度数据低通滤波器惯性系数，数值越小平滑效果越大，但滞后也越大。设定时不应当低于推荐值。
\item {\ttfamily dji\+\_\+motor\+\_\+measure}是\+DJI电机的反馈信息，包括当前编码器值、上次测量编码器值、速度、电流、温度、总圈数和单圈角度。
\item {\ttfamily \doxylink{struct_motor___control___setting__s}{Motor\+\_\+\+Control\+\_\+\+Setting\+\_\+s}}的定义在{\ttfamily \doxylink{motor__def_8h}{motor\+\_\+def.\+h}}之中，它和{\ttfamily \doxylink{struct_motor___controller__s}{Motor\+\_\+\+Controller\+\_\+s}}都是所有电机通用的组件（如\+M3508，\+LK9025，\+HT04，\+MT6023等），其包含内容如下：


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{struct\ }\textcolor{comment}{/*\ 电机控制配置\ */}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{motor__def_8h_a306d656c63a2d986e7aff57a0526395d}{Closeloop\_Type\_e}}\ outer\_loop\_type;}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{motor__def_8h_a306d656c63a2d986e7aff57a0526395d}{Closeloop\_Type\_e}}\ close\_loop\_type;}
\DoxyCodeLine{\ \ \ \ Motor\_Reverse\_Flag\_e\ motor\_reverse\_flag;}
\DoxyCodeLine{\ \ \ \ Feedback\_Source\_e\ angle\_feedback\_source;}
\DoxyCodeLine{\ \ \ \ Feedback\_Source\_e\ speed\_feedback\_source;}
\DoxyCodeLine{\}\ \mbox{\hyperlink{struct_motor___control___setting__s}{Motor\_Control\_Setting\_s}};}

\end{DoxyCode}


{\ttfamily \doxylink{struct_motor___control___setting__s}{Motor\+\_\+\+Control\+\_\+\+Setting\+\_\+s}}里包含了电机的闭环类型，反转标志以及额外的反馈来源标志。
\begin{DoxyItemize}
\item 闭环类型指示该电机使用的控制器配置，其枚举定义如下：


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{enum}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ CURRENT\_LOOP\ =\ 0b0001,}
\DoxyCodeLine{\ \ \ \ SPEED\_LOOP\ =\ 0b0010,}
\DoxyCodeLine{\ \ \ \ ANGLE\_LOOP\ =\ 0b0100,}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{struct__}{\_}}\ =\ 0b0011,}
\DoxyCodeLine{\ \ \ \ \_\_\ =\ 0b0110,}
\DoxyCodeLine{\ \ \ \ \_\_\_\ =\ 0b0111}
\DoxyCodeLine{\}\ \mbox{\hyperlink{motor__def_8h_a306d656c63a2d986e7aff57a0526395d}{Closeloop\_Type\_e}};}

\end{DoxyCode}


以\+M3508为例，假设需要进行\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}速度闭环\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}和\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}电流闭环\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，那么在初始化时就将这个变量的值设为{\ttfamily CURRENT\+\_\+\+LOOP \texorpdfstring{$\vert$}{|} SPEED\+\_\+\+LOOP}。在{\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}中，函数将会根据此标志位判断设定的参考值需要经过那些控制器的计算。 另外,你还需要设置当前电机的最外层闭环，即电机的闭环目标为什么类型的值。初始化时需要设置{\ttfamily outer\+\_\+loop\+\_\+type}。以\+M2006作为拨盘电机时为例，你希望它在单发/双发等固定发射数量的模式下对位置进行闭环（拨盘转过一定角度对应拨出一颗弹丸），但你也有可能希望在连发的时候让拨盘连续的转动，以一定的频率发射弹丸。我们提供了{\ttfamily DJIMotor\+Outer\+Loop()}用于修改电机的外层闭环，改变电机的闭环对象。

\texorpdfstring{$>$}{>} 注意，务必分清串级控制（多环）和外层闭环的区别。前者是为了提高内环的性能，使得其能更好地跟随外环参考值；而后者描述的是系统真实的控制目标（闭环目标）。如3508，没有电流环仍然可以对速度完成闭环，对于高层的应用来说，它们本质上不关心电机内部是否还有电流环，它们只把外层闭环为速度的电机当作一个\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}速度伺服执行器\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}外层闭环\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}描述的就是真正的闭环目标。
\item 为了避开恼人的正负号，提高代码的可维护性，在初始化电机时设定{\ttfamily motor\+\_\+reverse\+\_\+flag}使得所有电机都按照你想要的方向旋转，其定义如下：

{\ttfamily c typedef enum \{ MOTOR\+\_\+\+DIRECTION\+\_\+\+NORMAL = 0, MOTOR\+\_\+\+DIRECTION\+\_\+\+REVERSE = 1 \} Motor\+\_\+\+Reverse\+\_\+\+Flag\+\_\+e; }
\item {\ttfamily speed\+\_\+feedback\+\_\+source}以及{\ttfamily angle\+\_\+feedback\+\_\+source}是指示电机反馈来源的标志位。一般情况下电机使用自身的编码器作为控制反馈量。但在某些时候，如小陀螺模式，云台电机会使用\+IMU的姿态数据作为反馈数据来源。其定义如下：

{\ttfamily c typedef enum \{ MOTOR\+\_\+\+FEED = 0, OTHER\+\_\+\+FEED = 1 \} Feedback\+\_\+\+Source\+\_\+e; }

{\bfseries{注意，如果启用其他数据来源，你需要在电机的控制器配置{\ttfamily \doxylink{struct_motor___controller__s}{Motor\+\_\+\+Controller\+\_\+s}}下的{\ttfamily other\+\_\+xxx\+\_\+feedback\+\_\+ptr}中指定其他数据来源。}}

你可以在{\ttfamily DJIMotor\+Change\+Feed()}中修改电机的数据来源。
\end{DoxyItemize}
\item {\ttfamily \doxylink{struct_motor___controller__s}{Motor\+\_\+\+Controller\+\_\+s}}的定义也在{\ttfamily \doxylink{motor__def_8h}{motor\+\_\+def.\+h}}之中：


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{comment}{/*\ 电机控制器,包括其他来源的反馈数据指针,3环控制器和电机的参考输入*/}}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{struct}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ \textcolor{keywordtype}{float}\ *other\_angle\_feedback\_ptr;}
\DoxyCodeLine{\ \ \ \ \textcolor{keywordtype}{float}\ *other\_speed\_feedback\_ptr;}
\DoxyCodeLine{\ \ \ \ PID\_t\ current\_PID;}
\DoxyCodeLine{\ \ \ \ PID\_t\ speed\_PID;}
\DoxyCodeLine{\ \ \ \ PID\_t\ angle\_PID;}
\DoxyCodeLine{\ \ \ \ }
\DoxyCodeLine{\ \ \ \ \textcolor{keywordtype}{float}\ pid\_ref;\ \textcolor{comment}{//\ 将会作为每个环的输入和输出顺次通过串级闭环}}
\DoxyCodeLine{\}\ \mbox{\hyperlink{struct_motor___controller__s}{Motor\_Controller\_s}};}

\end{DoxyCode}


两个{\ttfamily float\texorpdfstring{$\ast$}{*}}指针应当指向其他反馈来源数据（如果有的话，需要在{\ttfamily motor\+\_\+settings}中设定）。

三个\+PID分别为三个控制闭环所用，在{\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}中，该函数会根据{\ttfamily close\+\_\+loop\+\_\+type}的设定计算对应的闭环。

{\bfseries{{\ttfamily pid\+\_\+ref}是控制的设定值，app层的应用想要更改电机的输出，就要调用{\ttfamily DJIMotor\+Set\+Ref()}更改此值。}}
\item {\ttfamily dji\+\_\+motor\+\_\+instance}是一个\+DJI电机实例。一个电机实例内包含电机的反馈信息，电机的控制设置，电机控制器，电机对应的\+CAN实例以及电机的类型；由于\+DJI电机支持\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}一帧报文控制至多4个电机\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，该结构体还包含了用于给电机分组发送进行特殊处理的{\ttfamily sender\+\_\+group}和{\ttfamily message\+\_\+num}（具体实现细节参考{\ttfamily Motor\+Sender\+Grouping()}函数）。
\end{DoxyItemize}\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md75}{}\doxysection{\texorpdfstring{外部接口}{外部接口}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md75}

\begin{DoxyCode}{0}
\DoxyCodeLine{dji\_motor\_instance\ *\mbox{\hyperlink{dji__motor_8h_ae6a2dbd0d46fc7d80c6e2339aad09969}{DJIMotorInit}}(can\_instance\_config\ config,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \mbox{\hyperlink{struct_motor___control___setting__s}{Motor\_Control\_Setting\_s}}\ motor\_setting,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \mbox{\hyperlink{struct_motor___controller___init__s}{Motor\_Controller\_Init\_s}}\ controller\_init,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Motor\_Type\_e\ type);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_afc682af85b4e84a7a74d01097cf738e5}{DJIMotorSetRef}}(dji\_motor\_instance\ *motor,\ \textcolor{keywordtype}{float}\ ref);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_af949d3574538d826035110bf7e05c2f8}{DJIMotorChangeFeed}}(dji\_motor\_instance\ *motor,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \mbox{\hyperlink{motor__def_8h_a306d656c63a2d986e7aff57a0526395d}{Closeloop\_Type\_e}}\ loop,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Feedback\_Source\_e\ type);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotorControl}}();}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ DJIMotorStop(dji\_motor\_instance\ *motor);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ DJIMotorEnable(dji\_motor\_instance\ *motor);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{dji__motor_8h_adbffe8a35fe1da0ed6c36227ce30f1cd}{DJIMotorOuterLoop}}(dji\_motor\_instance\ *motor);}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily DJIMotor\+Init()}是用于初始化电机对象的接口，传入包括电机can配置、电机控制配置、电机控制器配置以及电机类型在内的初始化参数。\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}它将会返回一个电机实例指针\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}，你应当在应用层保存这个指针，这样才能操控这个电机。
\item {\ttfamily DJIMotor\+Set\+Ref()}是设定电机输出的接口，\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}在调用这个函数的时候，你可以认为你的设定值会直接转变为电机的输出\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}。{\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}会帮你完成闭环计算，不用担心\+PID。
\item {\ttfamily DJIMotor\+Change\+Feed()}一般在更改云台或底盘的运动模式的时候被调用，传入要修改反馈来源的电机实例指针、要修改的闭环以及反馈来源类型。如希望切换到\+IMU的yaw值作为云台设定值，传入yaw轴电机实例和{\ttfamily ANGLE\+\_\+\+LOOP}（位置环）、{\ttfamily OTHER\+\_\+\+FEED}（启用其他数据来源）即可。当然，你需要在初始化的时候设定{\ttfamily motor\+\_\+controller}中的 {\ttfamily other\+\_\+angle\+\_\+feedback\+\_\+ptr}，使其指向yaw值的变量。
\item {\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}是根据电机的配置计算控制值的函数。该函数在{\ttfamily motor\+\_\+task.\+c}中被调用，应当在free\+RTOS中以一定频率运行。此函数为\+PID的计算进行了彻底的封装，要修改电机的参考输入，请在app层的应用中调用{\ttfamily DJIMotor\+Set\+Ref()}。

该函数的具体实现请参照代码，注释已经较为清晰。流程大致为：
\begin{DoxyEnumerate}
\item 根据电机的初始化控制配置，计算各个控制闭环
\item 根据反转标志位，确定是否将输出反转
\item 根据每个电机的发送分组，将最终输出值填入对应的分组buff
\item 检查每一个分组，若该分组有电机，发送报文
\end{DoxyEnumerate}
\item {\ttfamily DJIMotor\+Stop()}和{\ttfamily DJIMotor\+Enable()}用于控制电机的启动和停止。当电机被设为stop的时候，不会响应任何的参考输入。
\item {\ttfamily DJIMotor\+Outer\+Loop()}用于修改电机的外部闭环类型，即电机的真实闭环目标。
\end{DoxyItemize}\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md76}{}\doxysection{\texorpdfstring{私有函数和变量}{私有函数和变量}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md76}
在.\+c文件内设为static的函数和变量


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{static}\ uint8\_t\ idx\ =\ 0;\ \textcolor{comment}{//\ register\ idx,是该文件的全局电机索引,在注册时使用}}
\DoxyCodeLine{\textcolor{keyword}{static}\ dji\_motor\_instance\ *dji\_motor\_info[DJI\_MOTOR\_CNT]\ =\ \{NULL\};}

\end{DoxyCode}


这是管理所有电机实例的入口。idx用于电机初始化。


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ PI2\ (3.141592f\ *\ 2)}}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ ECD\_ANGLE\_COEF\_DJI\ 3.835e-\/4\ }\textcolor{comment}{//\ ecd/8192*pi}}

\end{DoxyCode}


这两个宏用于在电机反馈信息中的多圈角度计算，将编码器的0\texorpdfstring{$\sim$}{\string~}8192转化为角度表示。


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{comment}{/*\ @brief\ 由于DJI电机发送以四个一组的形式进行,故对其进行特殊处理,用6个(2can*3group)can\_instance专门负责发送}}
\DoxyCodeLine{\textcolor{comment}{\ *\ \ \ \ \ \ \ \ 该变量将在\ DJIMotorControl()\ 中使用,分组在\ MotorSenderGrouping()中进行}}
\DoxyCodeLine{\textcolor{comment}{\ *}}
\DoxyCodeLine{\textcolor{comment}{\ *\ can1:\ [0]:0x1FF,[1]:0x200,[2]:0x2FF}}
\DoxyCodeLine{\textcolor{comment}{\ *\ can2:\ [0]:0x1FF,[1]:0x200,[2]:0x2FF\ */}}
\DoxyCodeLine{\textcolor{keyword}{static}\ can\_instance\ sender\_assignment[6]\ =}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ \ \ \ \ [0]\ =\ \{.can\_handle\ =\ \&hcan1,\ .txconf.StdId\ =\ 0x1ff,\ .txconf.IDE\ =\ CAN\_ID\_STD,\ .txconf.RTR\ =\ CAN\_RTR\_DATA,\ .txconf.DLC\ =\ 0x08,\ .tx\_buff\ =\ \{0\}\},}
\DoxyCodeLine{\ \ ...}
\DoxyCodeLine{\ \ \ \ \ \ \ \ ...}
\DoxyCodeLine{\};}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static}\ uint8\_t\ sender\_enable\_flag[6]\ =\ \{0\};}

\end{DoxyCode}



\begin{DoxyItemize}
\item 这些是电机分组发送所需的变量。注册电机时，会根据挂载的总线以及发送id，将电机分组。在\+CAN发送电机控制信息的时候，根据{\ttfamily sender\+\_\+assignment\mbox{[}\mbox{]}}保存的分组进行发送，而不会使用电机实例自带的{\ttfamily can\+\_\+instance}。
\item DJI电机共有3种分组，分别为0x1\+FF,0x200,0x2\+FF。注册电机的时候，{\ttfamily Motor\+Sender\+Grouping()}函数会根据发送id计算出\+CAN的{\ttfamily tx\+\_\+id}（即上述三个中的一个）和{\ttfamily rx\+\_\+id}。然后为电机实例分配用于指示其在{\ttfamily sender\+\_\+assignment\mbox{[}\mbox{]}}中的编号的 {\ttfamily sender\+\_\+group}和其在该发送组中的位置{\ttfamily message\+\_\+num}（一帧报文可以发送四条控制指令，{\ttfamily message\+\_\+num}会指定电机是这四个中的哪一个）。具体的分配请查看{\ttfamily Motor\+Sender\+Grouping()}的定义。
\item 当某一个分组有电机注册时，该分组的索引将会在{\ttfamily sender\+\_\+enable\+\_\+flag}\mbox{[}\mbox{]}中被置1，这样，就可以避免发送没有电机注册的报文，防止总线拥塞。具体的，在{\ttfamily Decode\+DJIMotor()}中，该函数会查看{\ttfamily sender\+\_\+enable\+\_\+flag\mbox{[}\mbox{]}}的每一个位置，确定这一组是否有电机被注册，若有则发送{\ttfamily sender\+\_\+assignment\mbox{[}\mbox{]}}中对应位置的{\ttfamily tx\+\_\+buff}。
\end{DoxyItemize}


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{static}\ \textcolor{keywordtype}{void}\ IDcrash\_Handler(uint8\_t\ conflict\_motor\_idx,\ uint8\_t\ temp\_motor\_idx)}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static}\ \textcolor{keywordtype}{void}\ MotorSenderGrouping(can\_instance\_config\ *config)}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static}\ \textcolor{keywordtype}{void}\ DecodeDJIMotor(can\_instance\ *\_instance)}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily IDcrash\+\_\+\+Handler()}在电机id发生冲突的时候会被{\ttfamily Motor\+Sender\+Grouping()}调用，陷入死循环之中，并把冲突的id保存在函数里。这样就可以通过debug确定是否发生冲突以及冲突的编号。
\item {\ttfamily Motor\+Sender\+Grouping()}被{\ttfamily DJIMotor\+Init()}调用，他将会根据电机id计算出\+CAN的发送和接收\+ID，并根据发送\+ID对电机进行分组。
\item {\ttfamily Decode\+DJIMotor()}是解析电机反馈报文的函数，在{\ttfamily DJIMotor\+Init()}中会将其注册到该电机实例对应的{\ttfamily can\+\_\+instance}中（即{\ttfamily can\+\_\+instance}的{\ttfamily can\+\_\+module\+\_\+callback()}）。这样，当该电机的反馈报文到达时，{\ttfamily bsp\+\_\+can.\+c}中的回调函数会调用解包函数进行反馈数据解析。

该函数还会对电流和速度反馈值进行滤波，消除高频噪声；同时计算多圈角度和单圈绝对角度。

{\bfseries{电机反馈的电流值为说明书中的映射值，需转换为实际值。}}

{\bfseries{反馈的速度单位是rpm（转每分钟），转换为角度每秒。}}

{\bfseries{反馈的位置是编码器值（0\texorpdfstring{$\sim$}{\string~}8191），转换为角度。}}
\end{DoxyItemize}\hypertarget{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md77}{}\doxysection{\texorpdfstring{使用范例}{使用范例}}\label{md_modules_2motor_2_d_j_imotor_2dji__motor_autotoc_md77}

\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{comment}{//初始化设置}}
\DoxyCodeLine{\mbox{\hyperlink{struct_motor___init___config__s}{Motor\_Init\_Config\_s}}\ config\ =\ \{}
\DoxyCodeLine{\ \ .motor\_type\ =\ GM6020,}
\DoxyCodeLine{\ \ .can\_init\_config\ =\ \{}
\DoxyCodeLine{\ \ \ .can\_handle\ =\ \&hcan1,}
\DoxyCodeLine{\ \ \ .tx\_id\ =\ 6}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \},}
\DoxyCodeLine{\ \ .controller\_setting\_init\_config\ =\ \{}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .angle\_feedback\_source\ =\ MOTOR\_FEED,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .outer\_loop\_type\ =\ SPEED\_LOOP,}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .close\_loop\_type\ =\ SPEED\_LOOP\ |\ ANGLE\_LOOP,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .speed\_feedback\_source\ =\ MOTOR\_FEED,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .motor\_reverse\_flag\ =\ MOTOR\_DIRECTION\_NORMAL}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \},}
\DoxyCodeLine{\ \ .controller\_param\_init\_config\ =\ \{}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .angle\_PID\ =\ \{}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Improve\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kp\ =\ 1,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Ki\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kd\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .DeadBand\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .MaxOut\ =\ 4000\},\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ .speed\_PID\ =\ \{}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Improve\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kp\ =\ 1,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Ki\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .Kd\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .DeadBand\ =\ 0,\ }
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .MaxOut\ =\ 4000}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \ \ \ \ \}}
\DoxyCodeLine{\ \ \ \ \ \ \ \ \}}
\DoxyCodeLine{\};}
\DoxyCodeLine{\textcolor{comment}{//注册电机并保存实例指针}}
\DoxyCodeLine{dji\_motor\_instance\ *djimotor\ =\ \mbox{\hyperlink{dji__motor_8h_ae6a2dbd0d46fc7d80c6e2339aad09969}{DJIMotorInit}}(\&config);}

\end{DoxyCode}


然后在任务中修改电机设定值即可实现控制：


\begin{DoxyCode}{0}
\DoxyCodeLine{DJIMotorSetRef(djimotor,\ 10);}

\end{DoxyCode}


前提是已经将{\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}放入实时系统任务当中或以一定d。你也可以单独执行{\ttfamily \doxylink{dji__motor_8h_a550e8d4dd6e722e66552563550191c65}{DJIMotor\+Control()}}。 